<?php
declare(strict_types = 1);

namespace tool;

/**
 * 常见转换工具
 * @author Shanla
 */
class ConvertTool
{
	/**
	 * 数字转换成中文
	 *
	 * @author Shanla
	 * @param string|intger|float $num 数字
	 * @param integer $mode 模式[true:金额，false:普通数字]
	 * @param boolean $sim 使用小写
	 * @return string
	 */
	public static function numberToChinese($num, $mode = false, $sim = true)
	{
		$num = (string)$num;
		if(!is_numeric($num)) return '含有非数字非小数点字符！';

		$char = $sim ? array('零','一','二','三','四','五','六','七','八','九')
				: array('零','壹','贰','叁','肆','伍','陆','柒','捌','玖');
		$unit = $sim ? array('','十','百','千','','万','亿','兆')
				: array('','拾','佰','仟','','萬','億','兆');
		$retval = $mode ? '元':'点';

		//小数部分
		if(strpos($num, '.')){
			list($num,$dec) = explode('.', $num);
			$dec = strval(round($dec,2));

	        if($mode){
				$retval .= "{$char[$dec['0']]}角{$char[$dec['1']]}分";
			}else{
				for($i = 0,$c = strlen($dec);$i < $c;$i++) {
					$retval .= $char[$dec[$i]];
				}
			}
		}

		//整数部分
		$str = strrev($num);
		for($i = 0,$c = strlen($str);$i < $c;$i++) {
			$out[$i] = $char[$str[$i]];
			if($mode){
				$out[$i] .= $str[$i] != '0'? $unit[$i%4] : '';
				if($i>1 and $str[$i]+$str[$i-1] == 0){
					$out[$i] = '';
				}
				if($i%4 == 0){
					$out[$i] .= $unit[4+floor($i/4)];
				}
			}
		}
	    $retval = join('',array_reverse($out)) . $retval;
		return $retval;	
	}	

	/**
	 * 数组转xml
	 *
	 * @author Shanla
	 * @param array $arr
	 * @return string
	 */
	public static function arrayToXml(array $arr) : string
	{
		if (empty($arr)) return '';

		$xml = '<xml>';
		foreach($arr as $key => $value) {
			if (is_array($value)) {
				$child = [$key => $value];
				self::toXmlChild($child, $xml);
			} else {
				if (is_numeric($value)) {
					$xml .= "<" . $key . ">" . $value . "</" . $key . ">";
				} else {
					$xml .= "<" . $key . ">" . "<![CDATA[" . $value . "]]" . "</" . $key . ">";
				}
			}
		}
		$xml .= '<\xml>';

		return $xml;
	}

	/**
	 * array2Xml子类
	 *
	 * @author Shanla
	 * @param array $arr
	 * @param string $xml
	 */
	public static function toXmlChild(array $arr, string & $xml)
	{
		foreach($arr as $key => $value) {
			$xml .= "<" . $key . ">";
			if (is_array($val)) {
				foreach($value as $k => $v) {
					if (is_array($v)) {
						if (!is_numeric($k)) {
							$child = [$k => $v];
						} else {
							$child = $v;
						}
						self::toXmlChild($child, $xml);
					} else {
						if (is_numeric($value)) {
							$xml .= "<" . $key . ">" . $value . "</" . $key . ">";
						} else {
							$xml .= "<" . $key . ">" . "<![CDATA[" . $value . "]]" . "</" . $key . ">";
						}
					}
				}
			}
		}
	}

	/**
	 * xml转数组
	 *
	 * @author Shanla
	 * @param string $xml
	 * @return array
	 */
	public static function xmlToArray(string $xml) : array
	{
		return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
	}

	/**
	 * 图片文件转base64
	 *
	 * @author Shanla
	 * @param string $imageFile
	 * @return array
	 */
	public static function imageToBase64(string $imageFile) : string
	{
		$imageInfo = getimagesize($imageFile);
		$imageData = fread(fopen($imageFile, 'r'), filesize($imageFile));
		$base64 = 'data:' . $imageInfo['mime'] . ';base64,' . chunk_split(base64_encode($imageData));

		return $base64;
	}

	/**
	 * 出生日期转换年龄
	 * 
	 * @author Shanla
	 * @param string $birth 只支持"Y-m"格式
	 * @return int
	 */
	public static function birthToAge(string $birth) : int
	{
		$birth = explode("-", $birth);
		$birthYear = (int)$birth[0] ?? 0;
		if (0 == $birthYear) {
			return 0;
		}

		$currentYear = (int)date("Y", time());

		// 计算年龄
		$age = $currentYear - $birthYear + 1;
		return $age;
	}

	/**
	 * 年龄转年龄段
	 *
	 * @author Shanla
	 * @param int $age 年龄
	 * @param array $expArr 分隔数组
	 * @return string
	 */
	public static function ageToRange(int $age, array $expArr = [17, 24, 29, 39]) : string
	{
		foreach ($expArr as $key => $exp) {
			if ($age <= $exp) {
				if (0 == $key) {
					return $exp . '岁及以下';
				}
				if (strlen($expArr)-1 == $key) {
					return $exp . '岁及以上';
				}
				return $expArr[$key-1] . '岁-' . $exp . '岁';
			}
		}
		return '';
	}
}
